#include "uti_statistics.h"


extern char gTradingDay[15];

//1. init m_pdbinfo
//2. init m_buffer
CStatistics::CStatistics(string& strategy_id, map<string, OrderSysMapSeries*>&maptrademan):m_maptrademan(maptrademan), m_dbname_sufix("_statistics.db"), m_tablename("detail_table")
{
	//1. init m_pdbinfo
	if (false == InitDBInfo(strategy_id))
	{
		pantheios::log_ERROR("[CStatistics] InitDBInfo failed");
		return;
	}


	//2. init m_buffer
	if (false == InitBuffer())
	{
		printf("[CStatistics] InitBuffer failed\n");
		return;
	}

}


CStatistics::~CStatistics()
{
	DestroyBuffer();

	DestroyDBInfo();

}

bool CStatistics::InitDBInfo(string& strategy_id)
{
	string dbname = strategy_id + m_dbname_sufix;

	m_pdbinfo = new DBINFO(dbname);
	if (NULL == m_pdbinfo)
	{
		pantheios::log_ERROR("[InitDBInfo] m_pdbinfo NULL");
		return false;
	}

	m_pdbinfo->tbname.push_back(m_tablename);

	return true;
}

void CStatistics::DestroyDBInfo()
{
	if (m_pdbinfo)
	{
		delete m_pdbinfo;
	}
}



bool CStatistics::InitBuffer()
{
	m_buffer = new char[1024];//1K
	if (NULL == m_buffer)
	{
		pantheios::log_ERROR("[InitBuffer] m_buffer NULL");
		return false;
	}
	return true;

}

void CStatistics::DestroyBuffer()
{
	if (m_buffer)
	{
		delete[] m_buffer;
	}
}


bool CStatistics::WriteData()
{


	//1. Open DB
	if (false == OpenDB())
	{
		pantheios::log_ERROR("[WriteData] OpenDB failed");
		return false;
	}


	//2. WriteDB
	if (false == WriteDB()) 
	{
		pantheios::log_ERROR("[WriteData] WriteDB failed");
		return false;
	}

	//3. Close DB
	if (false == CloseDB())
	{
		pantheios::log_ERROR("[WriteData] CloseDB failed");
		return false;
	}

	return true;
}



bool CStatistics::OpenDB()
{

	try
	{
		SQLiteDatabase* &curpdb = m_pdbinfo->pdb;
		SQLiteStatement* &curpst = m_pdbinfo->pst;
		string& curdbname = m_pdbinfo->dbname;
		vector<string>& curtbname = m_pdbinfo->tbname;
		//string& curtbname = m_pdbinfo->tbname;

		/**********************Open DB********************************************/

		curpdb = new Kompex::SQLiteDatabase(curdbname, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
		// create statement instance for sql queries/statements
		curpst = new Kompex::SQLiteStatement(curpdb);

		/************************************************************************/


		/**********************Create First Table*****************************************/
		unsigned int tableindex = 0;


		memset(m_buffer, 0, sizeof(m_buffer));
		sprintf(m_buffer, "select name from sqlite_master where type='table' and name = '%s';", curtbname[tableindex].c_str());

		const char *tbName = (const char*)curpst->GetSqlResultCString(m_buffer);


		if (NULL == tbName)//table note exist, create it
		{
			memset(m_buffer, 0, sizeof(m_buffer));
				
			sprintf(m_buffer, "CREATE TABLE %s (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);", 
			curtbname[tableindex].c_str(), "id INTEGER PRIMARY KEY", "data VARCHAR(20)", "inst VARCHAR(20)",
			"buyopen_amount DOUBLE", "buyclose_amount DOUBLE", "buy_profit DOUBLE", "buyopen_commission DOUBLE", "buyclose_commission DOUBLE",
			"sellopen_amount DOUBLE", "sellclose_amount DOUBLE", "sell_profit DOUBLE", "sellopen_commission DOUBLE", "sellclose_commission DOUBLE",
			"total_profit DOUBLE");


			//printf(m_buffer);
			//int len = strlen(m_buffer);

			curpst->SqlStatement(m_buffer);


			//curpst->SqlStatement("PRAGMA synchronous=OFF;");
		}
		else//exist talbe for second write
		{
			pantheios::log_NOTICE("[OpenDB] db:", curdbname, " exist table:", curtbname[0].c_str());
		}

	
		/************************************************************************/

	}
	catch(Kompex::SQLiteException &exception)
	{
		std::cerr << "[OpenDB] Exception Occured" << std::endl;
		exception.Show();
		return false;
	}


	return true;
}



bool CStatistics::CloseDB()
{
	try
	{
		SQLiteDatabase* &curpdb = m_pdbinfo->pdb;
		SQLiteStatement* &curpst = m_pdbinfo->pst;
		string& curdbname = m_pdbinfo->dbname;
		//string& curtbname = m_pdbinfo->tbname;

		/**********************Close DB********************************************/

		if (curpdb)
		{
			delete curpdb;
		}

		if (curpst)
		{
			delete curpst;
		}

		/************************************************************************/


	}
	catch(Kompex::SQLiteException &exception)
	{
		std::cerr << "[CloseDB] \nException Occured" << std::endl;
		exception.Show();
		return false;
	}

	return true;
}

bool CStatistics::WriteDB()
{

	vector<string>& curtbname = m_pdbinfo->tbname;

	for (unsigned int index = 0; index < curtbname.size(); index++)
	{
		if (false == InsertDB(index))
		{
			printf("[WriteDB] InsertDB failed\n");
			return false;
		}


	}

	return true;
}


bool CStatistics::InsertDB(unsigned int index)
{
	SQLiteDatabase* &curpdb = m_pdbinfo->pdb;
	SQLiteStatement* &curpst = m_pdbinfo->pst;
	string& dbname = m_pdbinfo->dbname;
	string& tbName =  m_pdbinfo->tbname[index];

	
	try
	{

		curpst->BeginTransaction();

		unsigned int writeitem_cnt = 0;

		typedef map<string, OrderSysMapSeries*>::iterator it_mapser;
		for (it_mapser it = m_maptrademan.begin(); it != m_maptrademan.end(); it++)
		{
			const string &inst = (it->first); 

			OrderSysMapSeries* pmapser = it->second;

			// insert serprofit for each mapser
			OrderMapSerProfit eachser_profit;
			if (pmapser->GetOrdermapserProfit(eachser_profit))
			{
				memset(m_buffer, 0, sizeof(m_buffer));
				sprintf(m_buffer, "INSERT INTO %s (%s, %s, %s,\
								  %s, %s, %s, %s, %s,\
								  %s, %s, %s, %s, %s,\
								  %s)\
								  VALUES (NULL, '%s', '%s',\
								  %0.2f, %0.2f, %0.2f, %0.2f, %0.2f,\
								  %0.2f, %0.2f, %0.2f, %0.2f, %0.2f,\
								  %0.2f);", 
								  tbName.c_str(), "id", "data", "inst",
								  "buyopen_amount", "buyclose_amount", "buy_profit", "buyopen_commission", "buyclose_commission",
								  "sellopen_amount", "sellclose_amount", "sell_profit", "sellopen_commission", "sellclose_commission",
								  "total_profit",
								  gTradingDay, inst.c_str(), 
								  eachser_profit.buyopen_amount, eachser_profit.buyclose_amount, eachser_profit.buy_profit, eachser_profit.buyopen_commision, eachser_profit.buyclose_commision,
								  eachser_profit.sellopen_amount, eachser_profit.sellclose_amount, eachser_profit.sell_profit, eachser_profit.sellopen_commision, eachser_profit.sellclose_commision,
								  eachser_profit.totalprofit);

				//int len = strlen(m_buffer);
				//printf(m_buffer);	 

				curpst->SqlStatement(m_buffer);

				writeitem_cnt++;
			}
		}

		curpst->CommitTransaction();


		pantheios::log_NOTICE("[InsertDB] db:", dbname, " table:", tbName, " WriteCnt:", panint(writeitem_cnt));
	}
	catch(Kompex::SQLiteException &exception) 
	{
		std::cerr <<"[InsertDB] "<< dbname.c_str()<<" Exception Occured: " << exception.GetString();
		curpst->RollbackTransaction();
		std::cerr << "[InsertDB] Rollback was executed!" << std::endl;


		return false;
	}


	return true;




	//typedef map<string, OrderSysMapSeries*>::iterator it_mapser;
	//for (it_mapser it = m_maptrademan.begin(); it != m_maptrademan.end(); it++)
	//{
	//	const string &inst = (it->first); 

	//	OrderSysMapSeries* pmapser = it->second;

	//	// insert serprofit for each mapser
	//	OrderMapSerProfit eachser_profit;
	//	if (pmapser->GetOrdermapserProfit(eachser_profit))
	//	{
	//		try
	//		{
	//			curpst->BeginTransaction();


	//			memset(m_buffer, 0, sizeof(m_buffer));
	//			sprintf(m_buffer, "INSERT INTO %s (%s, %s, %s,\
	//							  %s, %s, %s, %s, %s,\
	//							  %s, %s, %s, %s, %s,\
	//							  %s)\
	//							  VALUES (NULL, '%s', '%s',\
	//							  %0.2f, %0.2f, %0.2f, %0.2f, %0.2f,\
	//							  %0.2f, %0.2f, %0.2f, %0.2f, %0.2f,\
	//							  %0.2f);", 
	//							  tbName.c_str(), "id", "data", "inst",
	//							  "buyopen_amount", "buyclose_amount", "buy_profit", "buyopen_commission", "buyclose_commission",
	//							  "sellopen_amount", "sellclose_amount", "sell_profit", "sellopen_commission", "sellclose_commission",
	//							  "total_profit",
	//							  gTradingDay, inst.c_str(), 
	//							  eachser_profit.buyopen_amount, eachser_profit.buyclose_amount, eachser_profit.buy_profit, eachser_profit.buyopen_commision, eachser_profit.buyclose_commision,
	//							  eachser_profit.sellopen_amount, eachser_profit.sellclose_amount, eachser_profit.sell_profit, eachser_profit.sellopen_commision, eachser_profit.sellclose_commision,
	//							  eachser_profit.totalprofit);

	//			//int len = strlen(m_buffer);

	//			printf(m_buffer);	 

	//			curpst->SqlStatement(m_buffer);


	//			curpst->CommitTransaction();
	//		}
	//		catch(Kompex::SQLiteException &exception) 
	//		{
	//			std::cerr <<"[InsertDB] "<< dbname.c_str()<<" Exception Occured: " << exception.GetString();
	//			curpst->RollbackTransaction();
	//			std::cerr << "[InsertDB] Rollback was executed!" << std::endl;


	//			return false;
	//		}

	//	}

	//}




}